{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "QspZPC3nYqVv"
   },
   "source": [
    "# 大模型都这么厉害了，还需要微调吗？0.6B的小模型还有什么意义吗？\n",
    "\n",
    "大家在日常使用Deepseek-R1或者是阿里新发布的Qwen3模型，他们的模型都是能力很强，所提供的API服也都可以满足大家的日常或者是公司开发所需。但大家也可以想一个简单的问题几个简单的问题，如下：\n",
    "\n",
    "1. 公司的数据是够敏感，是否需要保密？\n",
    "1. 日常使用大模型的任务是否很困难，对推理链是否刚需？\n",
    "1. 任务调用的大模型API并发量是多少？每日资金消耗有多少？\n",
    "\n",
    "对于问题1，如果公司数据敏感，那我建议不要调用供应商提供的大模型API。就算供应商保证不会拿你们数据做训练，但你们的数据还是泄漏了（会有不必要的风险），建议本地部署大模型。\n",
    "\n",
    "对于问题2，如果使用大模型的场景问题很困难并且刚需推理链，那可以使用供应商的API，这样可以保证推理链的上下文不会爆显存。如果问题很简单，没有刚需推理链，那建议本地部署小模型即可。\n",
    "\n",
    "对于问题3，如果任务很简单，且调用的大模型API并发量很高，那我建议微调一个特定任务的小模型，本地部署。这样可以满足高并发，并且可以减少资金消耗。（本地部署，默认硬件环境单卡4090）\n",
    "\n",
    "看到这里，想必大家已经思考完了以上三个问题，心中有了答案。那我给出一个小小的案例。\n",
    "\n",
    "## 微调模型的需求性\n",
    "\n",
    "假如你的公司有一个从投诉的文本中抽取用户信息的任务。比如，你需要从以下文本中抽取用户姓名、住址、邮箱、投诉的问题等等。\n",
    "\n",
    "> 这只是一个小小的案例，数据也是我用大模型批量制造的。真正的投诉数据不会这么“干净、整洁”。\n",
    "\n",
    "INPUT：\n",
    "```text\n",
    "龙琳，宁夏回族自治区璐市城东林街g座 955491，邮箱 nafan@example.com。小区垃圾堆积成山，晚上噪音扰人清梦，停车难上加难，简直无法忍受！\n",
    "```\n",
    "\n",
    "OUTPUT：\n",
    "```json\n",
    "{\n",
    "    \"name\": \"龙琳\",\n",
    "    \"address\": \"宁夏回族自治区璐市城东林街g座 955491\",\n",
    "    \"email\": \"nafan@example.com\",\n",
    "    \"question\": \"小区垃圾堆积成山，晚上噪音扰人清梦，停车难上加难，简直无法忍受！\"\n",
    "}\n",
    "```\n",
    "\n",
    "\n",
    "那你当然可以调用 Deepseek最强大的模型R1，也可以调用阿里最新发布最强大的模型 Qwen3-235B-A22B等等，这些模型的信息抽取效果也很非常的棒。\n",
    "\n",
    "但有个问题，如果你有几百万条这样的数据要处理，全部调用最新的，最好的大模型可能需要消耗几万块钱。并且，如果这些投诉数据，比如电信投诉数据，电网投诉数据，这些数据是敏感的不可以直接放到外网的。\n",
    "\n",
    "所以，综合数据敏感，和资金消耗。最好的选择就是微调一个小模型（如Qwen3-0.6B），既可以保证高并发，可以保证数据不泄漏，保证模型抽取的效果，还可以省钱！！！\n",
    "\n",
    "那下面，用一个小案例带大家实操一下，微调Qwen3-0.6B小模型完成文本信息抽取任务。\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "im4mN9cvK_Eb"
   },
   "source": [
    "## 配置环境 下载数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "executionInfo": {
     "elapsed": 2600,
     "status": "ok",
     "timestamp": 1748349187466,
     "user": {
      "displayName": "宋志学",
      "userId": "16203561073735324006"
     },
     "user_tz": -480
    },
    "id": "lL87ZhRBrZ8L"
   },
   "outputs": [],
   "source": [
    "!pip install datasets swanlab -q"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 2595,
     "status": "ok",
     "timestamp": 1748349190053,
     "user": {
      "displayName": "宋志学",
      "userId": "16203561073735324006"
     },
     "user_tz": -480
    },
    "id": "HVeg4pKrHm10",
    "outputId": "95d5f7e6-7242-4faf-baa6-3da3af0a6916"
   },
   "outputs": [],
   "source": [
    "!wget --no-check-certificate 'https://docs.google.com/uc?export=download&id=1a0sf5C209CLW5824TJkUM4olMy0zZWpg' -O fake_sft.json"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "1PEnxGDaLF1N"
   },
   "source": [
    "## 处理数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {
    "executionInfo": {
     "elapsed": 9,
     "status": "ok",
     "timestamp": 1748349190053,
     "user": {
      "displayName": "宋志学",
      "userId": "16203561073735324006"
     },
     "user_tz": -480
    },
    "id": "f7SfMcSip1qY"
   },
   "outputs": [],
   "source": [
    "from datasets import Dataset\n",
    "import pandas as pd\n",
    "from transformers import AutoTokenizer, AutoModelForCausalLM, DataCollatorForSeq2Seq, TrainingArguments, Trainer, GenerationConfig\n",
    "from peft import LoraConfig, TaskType, get_peft_model\n",
    "import torch"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 8,
     "status": "ok",
     "timestamp": 1748349190053,
     "user": {
      "displayName": "宋志学",
      "userId": "16203561073735324006"
     },
     "user_tz": -480
    },
    "id": "ntl6U3QovWDV",
    "outputId": "c3985a9e-af7f-4866-9967-293526e720cb"
   },
   "outputs": [],
   "source": [
    "# 将JSON文件转换为CSV文件\n",
    "df = pd.read_json('fake_sft.json')\n",
    "ds = Dataset.from_pandas(df)\n",
    "ds[:3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {
    "executionInfo": {
     "elapsed": 5,
     "status": "ok",
     "timestamp": 1748349190054,
     "user": {
      "displayName": "宋志学",
      "userId": "16203561073735324006"
     },
     "user_tz": -480
    },
    "id": "OwKDNPnJwxIq"
   },
   "outputs": [],
   "source": [
    "model_id = \"Qwen/Qwen3-0.6B\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 683,
     "status": "ok",
     "timestamp": 1748349190732,
     "user": {
      "displayName": "宋志学",
      "userId": "16203561073735324006"
     },
     "user_tz": -480
    },
    "id": "r5qVrTJSwbNE",
    "outputId": "82d4330a-5c48-4b48-bffc-ea040391c839"
   },
   "outputs": [],
   "source": [
    "tokenizer = AutoTokenizer.from_pretrained(model_id, use_fast=False)\n",
    "tokenizer"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "iT6MpvtEeVlA"
   },
   "source": [
    "对大语言模型进行 `supervised-finetuning`（`sft`，有监督微调）的数据格式如下：\n",
    "\n",
    "```json\n",
    "{\n",
    "  \"instruction\": \"回答以下用户问题，仅输出答案。\",\n",
    "  \"input\": \"1+1等于几?\",\n",
    "  \"output\": \"2\"\n",
    "}\n",
    "```\n",
    "\n",
    "其中，`instruction` 是用户指令，告知模型其需要完成的任务；`input` 是用户输入，是完成用户指令所必须的输入内容；`output` 是模型应该给出的输出。\n",
    "\n",
    "有监督微调的目标是让模型具备理解并遵循用户指令的能力。因此，在构建数据集时，我们应针对我们的目标任务，针对性构建数据。比如，如果我们的目标是通过大量人物的对话数据微调得到一个能够 role-play 甄嬛对话风格的模型，因此在该场景下的数据示例如下：\n",
    "\n",
    "```json\n",
    "{\n",
    "  \"instruction\": \"你父亲是谁？\",\n",
    "  \"input\": \"\",\n",
    "  \"output\": \"家父是大理寺少卿甄远道。\"\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "7n5BUDe0eing"
   },
   "source": [
    "`Qwen3` 采用的 `Chat Template`格式如下：\n",
    "\n",
    "由于 `Qwen3` 是混合推理模型，因此可以手动选择开启思考模式\n",
    "\n",
    "不开启 `thinking mode`\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 7,
     "status": "ok",
     "timestamp": 1748349190732,
     "user": {
      "displayName": "宋志学",
      "userId": "16203561073735324006"
     },
     "user_tz": -480
    },
    "id": "BVLy77FPUkas",
    "outputId": "4bfb0885-8c40-47be-cbfc-e4bb0b7ca34a"
   },
   "outputs": [],
   "source": [
    "messages = [\n",
    "    {\"role\": \"system\", \"content\": \"You are a helpful AI\"},\n",
    "    {\"role\": \"user\", \"content\": \"你怎么样？\"},\n",
    "    {\"role\": \"assistant\", \"content\": \"I'm fine, think you. and you?\"},\n",
    "]\n",
    "\n",
    "text = tokenizer.apply_chat_template(\n",
    "    messages,\n",
    "    tokenize=False,\n",
    "    add_generation_prompt=True,\n",
    "    enable_thinking=False\n",
    ")\n",
    "print(text)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "E_9FLMFbeci9"
   },
   "source": [
    "`LoRA`（`Low-Rank Adaptation`）训练的数据是需要经过格式化、编码之后再输入给模型进行训练的，我们需要先将输入文本编码为 `input_ids`，将输出文本编码为 `labels`，编码之后的结果是向量。我们首先定义一个预处理函数，这个函数用于对每一个样本，同时编码其输入、输出文本并返回一个编码后的字典："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {
    "executionInfo": {
     "elapsed": 4,
     "status": "ok",
     "timestamp": 1748349190732,
     "user": {
      "displayName": "宋志学",
      "userId": "16203561073735324006"
     },
     "user_tz": -480
    },
    "id": "_SZd9f-YxD5F"
   },
   "outputs": [],
   "source": [
    "def process_func(example):\n",
    "    MAX_LENGTH = 1024 # 设置最大序列长度为1024个token\n",
    "    input_ids, attention_mask, labels = [], [], [] # 初始化返回值\n",
    "    # 适配chat_template\n",
    "    instruction = tokenizer(\n",
    "        f\"<s><|im_start|>system\\n{example['system']}<|im_end|>\\n\"\n",
    "        f\"<|im_start|>user\\n{example['instruction'] + example['input']}<|im_end|>\\n\"\n",
    "        f\"<|im_start|>assistant\\n<think>\\n\\n</think>\\n\\n\",\n",
    "        add_special_tokens=False\n",
    "    )\n",
    "    response = tokenizer(f\"{example['output']}\", add_special_tokens=False)\n",
    "    # 将instructio部分和response部分的input_ids拼接，并在末尾添加eos token作为标记结束的token\n",
    "    input_ids = instruction[\"input_ids\"] + response[\"input_ids\"] + [tokenizer.pad_token_id]\n",
    "    # 注意力掩码，表示模型需要关注的位置\n",
    "    attention_mask = instruction[\"attention_mask\"] + response[\"attention_mask\"] + [1]\n",
    "    # 对于instruction，使用-100表示这些位置不计算loss（即模型不需要预测这部分）\n",
    "    labels = [-100] * len(instruction[\"input_ids\"]) + response[\"input_ids\"] + [tokenizer.pad_token_id]\n",
    "    if len(input_ids) > MAX_LENGTH:  # 超出最大序列长度截断\n",
    "        input_ids = input_ids[:MAX_LENGTH]\n",
    "        attention_mask = attention_mask[:MAX_LENGTH]\n",
    "        labels = labels[:MAX_LENGTH]\n",
    "    return {\n",
    "        \"input_ids\": input_ids,\n",
    "        \"attention_mask\": attention_mask,\n",
    "        \"labels\": labels\n",
    "    }\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 120,
     "referenced_widgets": [
      "19f8ad919f654fb68804224ed09ad40a",
      "6ce9fe53e5514f11b9a31888aebd6fb5",
      "243b04d90efe425ba9bac4b06a9cfae5",
      "78fdd9a50a8a43209e00c15e00b96bf3",
      "fe56ff681812418f8189e2e083c99f28",
      "e1de9fca5e444275a09f61e981426b39",
      "34e10a0497c4400ba06103e13478cd15",
      "fa657afaafc84f0db9993343e9057ca1",
      "50f8d1d0ead1479580e53e7f6704177b",
      "317c815eac5b46d7b1c91346c3433f58",
      "1508e978fbc3438aad918f1d201b6be3"
     ]
    },
    "executionInfo": {
     "elapsed": 3016,
     "status": "ok",
     "timestamp": 1748349193745,
     "user": {
      "displayName": "宋志学",
      "userId": "16203561073735324006"
     },
     "user_tz": -480
    },
    "id": "uRiURTdjxSeM",
    "outputId": "604b1256-e141-4a2e-ccee-6cd1ca5ae9dc"
   },
   "outputs": [],
   "source": [
    "tokenized_id = ds.map(process_func, remove_columns=ds.column_names)\n",
    "tokenized_id"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 71
    },
    "executionInfo": {
     "elapsed": 22,
     "status": "ok",
     "timestamp": 1748349193745,
     "user": {
      "displayName": "宋志学",
      "userId": "16203561073735324006"
     },
     "user_tz": -480
    },
    "id": "XJP9lUluxVHC",
    "outputId": "ca91df64-880a-480b-91c2-d68644df277e"
   },
   "outputs": [],
   "source": [
    "tokenizer.decode(tokenized_id[0]['input_ids'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 35
    },
    "executionInfo": {
     "elapsed": 20,
     "status": "ok",
     "timestamp": 1748349193746,
     "user": {
      "displayName": "宋志学",
      "userId": "16203561073735324006"
     },
     "user_tz": -480
    },
    "id": "_gZqo6F1xXHG",
    "outputId": "ea9a4e71-a43a-4653-96ce-b36d7f55567d"
   },
   "outputs": [],
   "source": [
    "tokenizer.decode(list(filter(lambda x: x != -100, tokenized_id[1][\"labels\"])))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "TyaeU92nLWM0"
   },
   "source": [
    "## 加载模型\n",
    "\n",
    "加载模型并配置LoraConfig\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 1284,
     "status": "ok",
     "timestamp": 1748349195012,
     "user": {
      "displayName": "宋志学",
      "userId": "16203561073735324006"
     },
     "user_tz": -480
    },
    "id": "Nm52b7DjxaTo",
    "outputId": "9570c9d6-0276-4976-b644-559c73f89d4e"
   },
   "outputs": [],
   "source": [
    "model = AutoModelForCausalLM.from_pretrained(model_id, device_map=\"auto\",torch_dtype=torch.bfloat16)\n",
    "model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {
    "executionInfo": {
     "elapsed": 18,
     "status": "ok",
     "timestamp": 1748349195012,
     "user": {
      "displayName": "宋志学",
      "userId": "16203561073735324006"
     },
     "user_tz": -480
    },
    "id": "yb8dx7VuxhCZ"
   },
   "outputs": [],
   "source": [
    "model.enable_input_require_grads() # 开启梯度检查点时，要执行该方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 16,
     "status": "ok",
     "timestamp": 1748349195012,
     "user": {
      "displayName": "宋志学",
      "userId": "16203561073735324006"
     },
     "user_tz": -480
    },
    "id": "h6ifuYgGxlnR",
    "outputId": "3bdf7e49-5ae7-4209-e19a-76f14a1cae77"
   },
   "outputs": [],
   "source": [
    "model.dtype"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "4ipl2n3eevry"
   },
   "source": [
    "## Lora Config\n",
    "\n",
    "`LoraConfig`这个类中可以设置很多参数，比较重要的如下\n",
    "\n",
    "- `task_type`：模型类型，现在绝大部分 `decoder_only` 的模型都是因果语言模型 `CAUSAL_LM`\n",
    "- `target_modules`：需要训练的模型层的名字，主要就是 `attention`部分的层，不同的模型对应的层的名字不同\n",
    "- `r`：`LoRA` 的秩，决定了低秩矩阵的维度，较小的 `r` 意味着更少的参数\n",
    "- `lora_alpha`：缩放参数，与 `r` 一起决定了 `LoRA` 更新的强度。实际缩放比例为`lora_alpha/r`，在当前示例中是 `32 / 8 = 4` 倍\n",
    "- `lora_dropout`：应用于 `LoRA` 层的 `dropout rate`，用于防止过拟合\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 13,
     "status": "ok",
     "timestamp": 1748349195012,
     "user": {
      "displayName": "宋志学",
      "userId": "16203561073735324006"
     },
     "user_tz": -480
    },
    "id": "BW5m_60Exn5m",
    "outputId": "3de08863-e89a-40e0-f86b-1e455ddd43aa"
   },
   "outputs": [],
   "source": [
    "from peft import LoraConfig, TaskType, get_peft_model\n",
    "\n",
    "config = LoraConfig(\n",
    "    task_type=TaskType.CAUSAL_LM,\n",
    "    target_modules=[\"q_proj\", \"k_proj\", \"v_proj\", \"o_proj\", \"gate_proj\", \"up_proj\", \"down_proj\"],\n",
    "    inference_mode=False, # 训练模式\n",
    "    r=8, # Lora 秩\n",
    "    lora_alpha=32, # Lora alaph，具体作用参见 Lora 原理\n",
    "    lora_dropout=0.1# Dropout 比例\n",
    ")\n",
    "config"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 742,
     "status": "ok",
     "timestamp": 1748349195749,
     "user": {
      "displayName": "宋志学",
      "userId": "16203561073735324006"
     },
     "user_tz": -480
    },
    "id": "6w1Q_2-HxrAC",
    "outputId": "9b516801-b5eb-403f-de31-ae94632403e2"
   },
   "outputs": [],
   "source": [
    "model = get_peft_model(model, config)\n",
    "config"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 11,
     "status": "ok",
     "timestamp": 1748349195749,
     "user": {
      "displayName": "宋志学",
      "userId": "16203561073735324006"
     },
     "user_tz": -480
    },
    "id": "5pY-ZniqxsiU",
    "outputId": "6e5ee326-2b29-4c6a-a6b2-7fa7f8e61a94"
   },
   "outputs": [],
   "source": [
    "model.print_trainable_parameters()  # 模型参数训练量只有0.8395%"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "RGzo4FA2Lmh8"
   },
   "source": [
    "## Training Arguments\n",
    "\n",
    "- `output_dir`：模型的输出路径\n",
    "- `per_device_train_batch_size`：每张卡上的 `batch_size`\n",
    "- `gradient_accumulation_steps`: 梯度累计\n",
    "- `num_train_epochs`：顾名思义 `epoch`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {
    "executionInfo": {
     "elapsed": 9,
     "status": "ok",
     "timestamp": 1748349195750,
     "user": {
      "displayName": "宋志学",
      "userId": "16203561073735324006"
     },
     "user_tz": -480
    },
    "id": "GGZfByS6xt77"
   },
   "outputs": [],
   "source": [
    "args = TrainingArguments(\n",
    "    output_dir=\"Qwen3_instruct_lora\",\n",
    "    per_device_train_batch_size=4,\n",
    "    gradient_accumulation_steps=4,\n",
    "    logging_steps=1,\n",
    "    num_train_epochs=3,\n",
    "    save_steps=50,\n",
    "    learning_rate=1e-4,\n",
    "    save_on_each_node=True,\n",
    "    gradient_checkpointing=True,\n",
    "    report_to=\"none\",\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Ob5W-rUZfB1A"
   },
   "source": [
    "## SwanLab 简介\n",
    "\n",
    "![](./images/05-2.png)\n",
    "\n",
    "[SwanLab](https://github.com/swanhubx/swanlab) 是一个开源的模型训练记录工具，面向 AI 研究者，提供了训练可视化、自动日志记录、超参数记录、实验对比、多人协同等功能。在 `SwanLab` 上，研究者能基于直观的可视化图表发现训练问题，对比多个实验找到研究灵感，并通过在线链接的分享与基于组织的多人协同训练，打破团队沟通的壁垒。\n",
    "\n",
    "**为什么要记录训练**\n",
    "\n",
    "相较于软件开发，模型训练更像一个实验科学。一个品质优秀的模型背后，往往是成千上万次实验。研究者需要不断尝试、记录、对比，积累经验，才能找到最佳的模型结构、超参数与数据配比。在这之中，如何高效进行记录与对比，对于研究效率的提升至关重要。\n",
    "\n",
    "`(2) Use an existing SwanLab account` 并使用 private API Key 登录\n",
    "\n",
    "```python\n",
    "import swanlab\n",
    "from swanlab.integration.transformers import SwanLabCallback\n",
    "\n",
    "# 实例化SwanLabCallback\n",
    "swanlab_callback = SwanLabCallback(\n",
    "    project=\"Qwen3-Lora\",  # 注意修改\n",
    "    experiment_name=\"Qwen3-8B-LoRA-experiment\"  # 注意修改\n",
    ")\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {
    "executionInfo": {
     "elapsed": 9,
     "status": "ok",
     "timestamp": 1748349195750,
     "user": {
      "displayName": "宋志学",
      "userId": "16203561073735324006"
     },
     "user_tz": -480
    },
    "id": "eNBJKvAeWB64"
   },
   "outputs": [],
   "source": [
    "import swanlab\n",
    "from swanlab.integration.transformers import SwanLabCallback\n",
    "\n",
    "# 实例化SwanLabCallback\n",
    "swanlab_callback = SwanLabCallback(\n",
    "    project=\"Qwen3-Lora\",\n",
    "    experiment_name=\"Qwen3-0.6B-extarct-lora-2\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 8,
     "status": "ok",
     "timestamp": 1748349195750,
     "user": {
      "displayName": "宋志学",
      "userId": "16203561073735324006"
     },
     "user_tz": -480
    },
    "id": "smh8KKpvxxs9",
    "outputId": "b50afab9-460a-4133-fdeb-8933a047a1ec"
   },
   "outputs": [],
   "source": [
    "trainer = Trainer(\n",
    "    model=model,\n",
    "    args=args,\n",
    "    train_dataset=tokenized_id,\n",
    "    data_collator=DataCollatorForSeq2Seq(tokenizer=tokenizer, padding=True),\n",
    "    callbacks=[swanlab_callback]\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 1000
    },
    "executionInfo": {
     "elapsed": 302595,
     "status": "ok",
     "timestamp": 1748349498339,
     "user": {
      "displayName": "宋志学",
      "userId": "16203561073735324006"
     },
     "user_tz": -480
    },
    "id": "br1b42z1yIVa",
    "outputId": "e2218a24-47fe-4271-e073-9960648dbb6e"
   },
   "outputs": [],
   "source": [
    "trainer.train()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "BwEOEg_ZzD0c"
   },
   "source": [
    "## 测试文本"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 20262,
     "status": "ok",
     "timestamp": 1748349700049,
     "user": {
      "displayName": "宋志学",
      "userId": "16203561073735324006"
     },
     "user_tz": -480
    },
    "id": "LN-wQRsLzFek",
    "outputId": "4fcb1e4e-2271-4cbc-e4e1-84392e8fd39d"
   },
   "outputs": [],
   "source": [
    "prompt = \"龙琳   ，宁夏回族自治区璐市城东林街g座 955491，nafan@example.com。小区垃圾堆积成山，晚上噪音扰人清梦，停车难上加难，简直无法忍受！太插件了阿萨德看见啊啥的健康仨都会撒娇看到撒谎的、\"\n",
    "\n",
    "messages = [\n",
    "    {\"role\": \"system\", \"content\": \"将文本中的name、address、email、question提取出来，以json格式输出，字段为name、address、email、question，值为文本中提取出来的内容。\"},\n",
    "    {\"role\": \"user\", \"content\": prompt}\n",
    "]\n",
    "\n",
    "inputs = tokenizer.apply_chat_template(messages,\n",
    "                                       add_generation_prompt=True,\n",
    "                                       tokenize=True,\n",
    "                                       return_tensors=\"pt\",\n",
    "                                       return_dict=True,\n",
    "                                       enable_thinking=False).to('cuda')\n",
    "\n",
    "gen_kwargs = {\"max_length\": 2500, \"do_sample\": True, \"top_k\": 1}\n",
    "with torch.no_grad():\n",
    "    outputs = model.generate(**inputs, **gen_kwargs)\n",
    "    outputs = outputs[:, inputs['input_ids'].shape[1]:]\n",
    "    print(tokenizer.decode(outputs[0], skip_special_tokens=True))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {
    "executionInfo": {
     "elapsed": 7,
     "status": "ok",
     "timestamp": 1748349511232,
     "user": {
      "displayName": "宋志学",
      "userId": "16203561073735324006"
     },
     "user_tz": -480
    },
    "id": "V2ZXcgWRgsrW"
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "accelerator": "GPU",
  "colab": {
   "authorship_tag": "ABX9TyPuZmmvREGBWpTknYUbWhyz",
   "gpuType": "T4",
   "mount_file_id": "18ByY11KVhIy6zWx1uKUjSzqeHTme-TtU",
   "provenance": []
  },
  "kernelspec": {
   "display_name": "nlp",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.10.13"
  },
  "widgets": {
   "application/vnd.jupyter.widget-state+json": {
    "1508e978fbc3438aad918f1d201b6be3": {
     "model_module": "@jupyter-widgets/controls",
     "model_module_version": "1.5.0",
     "model_name": "DescriptionStyleModel",
     "state": {
      "_model_module": "@jupyter-widgets/controls",
      "_model_module_version": "1.5.0",
      "_model_name": "DescriptionStyleModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/base",
      "_view_module_version": "1.2.0",
      "_view_name": "StyleView",
      "description_width": ""
     }
    },
    "19f8ad919f654fb68804224ed09ad40a": {
     "model_module": "@jupyter-widgets/controls",
     "model_module_version": "1.5.0",
     "model_name": "HBoxModel",
     "state": {
      "_dom_classes": [],
      "_model_module": "@jupyter-widgets/controls",
      "_model_module_version": "1.5.0",
      "_model_name": "HBoxModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/controls",
      "_view_module_version": "1.5.0",
      "_view_name": "HBoxView",
      "box_style": "",
      "children": [
       "IPY_MODEL_6ce9fe53e5514f11b9a31888aebd6fb5",
       "IPY_MODEL_243b04d90efe425ba9bac4b06a9cfae5",
       "IPY_MODEL_78fdd9a50a8a43209e00c15e00b96bf3"
      ],
      "layout": "IPY_MODEL_fe56ff681812418f8189e2e083c99f28"
     }
    },
    "243b04d90efe425ba9bac4b06a9cfae5": {
     "model_module": "@jupyter-widgets/controls",
     "model_module_version": "1.5.0",
     "model_name": "FloatProgressModel",
     "state": {
      "_dom_classes": [],
      "_model_module": "@jupyter-widgets/controls",
      "_model_module_version": "1.5.0",
      "_model_name": "FloatProgressModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/controls",
      "_view_module_version": "1.5.0",
      "_view_name": "ProgressView",
      "bar_style": "success",
      "description": "",
      "description_tooltip": null,
      "layout": "IPY_MODEL_fa657afaafc84f0db9993343e9057ca1",
      "max": 300,
      "min": 0,
      "orientation": "horizontal",
      "style": "IPY_MODEL_50f8d1d0ead1479580e53e7f6704177b",
      "value": 300
     }
    },
    "317c815eac5b46d7b1c91346c3433f58": {
     "model_module": "@jupyter-widgets/base",
     "model_module_version": "1.2.0",
     "model_name": "LayoutModel",
     "state": {
      "_model_module": "@jupyter-widgets/base",
      "_model_module_version": "1.2.0",
      "_model_name": "LayoutModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/base",
      "_view_module_version": "1.2.0",
      "_view_name": "LayoutView",
      "align_content": null,
      "align_items": null,
      "align_self": null,
      "border": null,
      "bottom": null,
      "display": null,
      "flex": null,
      "flex_flow": null,
      "grid_area": null,
      "grid_auto_columns": null,
      "grid_auto_flow": null,
      "grid_auto_rows": null,
      "grid_column": null,
      "grid_gap": null,
      "grid_row": null,
      "grid_template_areas": null,
      "grid_template_columns": null,
      "grid_template_rows": null,
      "height": null,
      "justify_content": null,
      "justify_items": null,
      "left": null,
      "margin": null,
      "max_height": null,
      "max_width": null,
      "min_height": null,
      "min_width": null,
      "object_fit": null,
      "object_position": null,
      "order": null,
      "overflow": null,
      "overflow_x": null,
      "overflow_y": null,
      "padding": null,
      "right": null,
      "top": null,
      "visibility": null,
      "width": null
     }
    },
    "34e10a0497c4400ba06103e13478cd15": {
     "model_module": "@jupyter-widgets/controls",
     "model_module_version": "1.5.0",
     "model_name": "DescriptionStyleModel",
     "state": {
      "_model_module": "@jupyter-widgets/controls",
      "_model_module_version": "1.5.0",
      "_model_name": "DescriptionStyleModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/base",
      "_view_module_version": "1.2.0",
      "_view_name": "StyleView",
      "description_width": ""
     }
    },
    "50f8d1d0ead1479580e53e7f6704177b": {
     "model_module": "@jupyter-widgets/controls",
     "model_module_version": "1.5.0",
     "model_name": "ProgressStyleModel",
     "state": {
      "_model_module": "@jupyter-widgets/controls",
      "_model_module_version": "1.5.0",
      "_model_name": "ProgressStyleModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/base",
      "_view_module_version": "1.2.0",
      "_view_name": "StyleView",
      "bar_color": null,
      "description_width": ""
     }
    },
    "6ce9fe53e5514f11b9a31888aebd6fb5": {
     "model_module": "@jupyter-widgets/controls",
     "model_module_version": "1.5.0",
     "model_name": "HTMLModel",
     "state": {
      "_dom_classes": [],
      "_model_module": "@jupyter-widgets/controls",
      "_model_module_version": "1.5.0",
      "_model_name": "HTMLModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/controls",
      "_view_module_version": "1.5.0",
      "_view_name": "HTMLView",
      "description": "",
      "description_tooltip": null,
      "layout": "IPY_MODEL_e1de9fca5e444275a09f61e981426b39",
      "placeholder": "​",
      "style": "IPY_MODEL_34e10a0497c4400ba06103e13478cd15",
      "value": "Map: 100%"
     }
    },
    "78fdd9a50a8a43209e00c15e00b96bf3": {
     "model_module": "@jupyter-widgets/controls",
     "model_module_version": "1.5.0",
     "model_name": "HTMLModel",
     "state": {
      "_dom_classes": [],
      "_model_module": "@jupyter-widgets/controls",
      "_model_module_version": "1.5.0",
      "_model_name": "HTMLModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/controls",
      "_view_module_version": "1.5.0",
      "_view_name": "HTMLView",
      "description": "",
      "description_tooltip": null,
      "layout": "IPY_MODEL_317c815eac5b46d7b1c91346c3433f58",
      "placeholder": "​",
      "style": "IPY_MODEL_1508e978fbc3438aad918f1d201b6be3",
      "value": " 300/300 [00:01&lt;00:00, 278.80 examples/s]"
     }
    },
    "e1de9fca5e444275a09f61e981426b39": {
     "model_module": "@jupyter-widgets/base",
     "model_module_version": "1.2.0",
     "model_name": "LayoutModel",
     "state": {
      "_model_module": "@jupyter-widgets/base",
      "_model_module_version": "1.2.0",
      "_model_name": "LayoutModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/base",
      "_view_module_version": "1.2.0",
      "_view_name": "LayoutView",
      "align_content": null,
      "align_items": null,
      "align_self": null,
      "border": null,
      "bottom": null,
      "display": null,
      "flex": null,
      "flex_flow": null,
      "grid_area": null,
      "grid_auto_columns": null,
      "grid_auto_flow": null,
      "grid_auto_rows": null,
      "grid_column": null,
      "grid_gap": null,
      "grid_row": null,
      "grid_template_areas": null,
      "grid_template_columns": null,
      "grid_template_rows": null,
      "height": null,
      "justify_content": null,
      "justify_items": null,
      "left": null,
      "margin": null,
      "max_height": null,
      "max_width": null,
      "min_height": null,
      "min_width": null,
      "object_fit": null,
      "object_position": null,
      "order": null,
      "overflow": null,
      "overflow_x": null,
      "overflow_y": null,
      "padding": null,
      "right": null,
      "top": null,
      "visibility": null,
      "width": null
     }
    },
    "fa657afaafc84f0db9993343e9057ca1": {
     "model_module": "@jupyter-widgets/base",
     "model_module_version": "1.2.0",
     "model_name": "LayoutModel",
     "state": {
      "_model_module": "@jupyter-widgets/base",
      "_model_module_version": "1.2.0",
      "_model_name": "LayoutModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/base",
      "_view_module_version": "1.2.0",
      "_view_name": "LayoutView",
      "align_content": null,
      "align_items": null,
      "align_self": null,
      "border": null,
      "bottom": null,
      "display": null,
      "flex": null,
      "flex_flow": null,
      "grid_area": null,
      "grid_auto_columns": null,
      "grid_auto_flow": null,
      "grid_auto_rows": null,
      "grid_column": null,
      "grid_gap": null,
      "grid_row": null,
      "grid_template_areas": null,
      "grid_template_columns": null,
      "grid_template_rows": null,
      "height": null,
      "justify_content": null,
      "justify_items": null,
      "left": null,
      "margin": null,
      "max_height": null,
      "max_width": null,
      "min_height": null,
      "min_width": null,
      "object_fit": null,
      "object_position": null,
      "order": null,
      "overflow": null,
      "overflow_x": null,
      "overflow_y": null,
      "padding": null,
      "right": null,
      "top": null,
      "visibility": null,
      "width": null
     }
    },
    "fe56ff681812418f8189e2e083c99f28": {
     "model_module": "@jupyter-widgets/base",
     "model_module_version": "1.2.0",
     "model_name": "LayoutModel",
     "state": {
      "_model_module": "@jupyter-widgets/base",
      "_model_module_version": "1.2.0",
      "_model_name": "LayoutModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/base",
      "_view_module_version": "1.2.0",
      "_view_name": "LayoutView",
      "align_content": null,
      "align_items": null,
      "align_self": null,
      "border": null,
      "bottom": null,
      "display": null,
      "flex": null,
      "flex_flow": null,
      "grid_area": null,
      "grid_auto_columns": null,
      "grid_auto_flow": null,
      "grid_auto_rows": null,
      "grid_column": null,
      "grid_gap": null,
      "grid_row": null,
      "grid_template_areas": null,
      "grid_template_columns": null,
      "grid_template_rows": null,
      "height": null,
      "justify_content": null,
      "justify_items": null,
      "left": null,
      "margin": null,
      "max_height": null,
      "max_width": null,
      "min_height": null,
      "min_width": null,
      "object_fit": null,
      "object_position": null,
      "order": null,
      "overflow": null,
      "overflow_x": null,
      "overflow_y": null,
      "padding": null,
      "right": null,
      "top": null,
      "visibility": null,
      "width": null
     }
    }
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
